package imgoptimizer

import (
	"bytes"
	"image"
	"image/color"
	"image/draw"
	"image/jpeg"
	"image/png"
	"io"

	// "github.com/Kagami/go-avif"
	"github.com/anthonynsimon/bild/transform"
	"github.com/chai2010/webp"
	"github.com/disintegration/imaging"
)

type imgOptimizer struct {
	img image.Image
	// xBound   int
	// yBound   int
	// mimetype string
}

func Decode(r io.Reader) (*imgOptimizer, error) {
	m, err := imaging.Decode(r, imaging.AutoOrientation(true))
	return &imgOptimizer{img: m}, err
}

// Downsize 缩小图片尺寸，会保持宽高比例
// preserving the aspect ratio
func (i *imgOptimizer) Downsize(maxW, maxH int) *imgOptimizer {
	maxX, maxY := i.img.Bounds().Max.X, i.img.Bounds().Max.Y
	if maxX <= maxW && maxY <= maxH {
		return i
	}

	if (float32(maxX) / float32(maxW)) > (float32(maxY) / float32(maxH)) {
		maxH = 0
	} else {
		maxW = 0
	}
	i.img = imaging.Resize(i.img, maxW, maxH, imaging.Lanczos)
	return i
}

// ToJPG (quality: 0-100)
func (i *imgOptimizer) ToJPG(quality int) ([]byte, error) {
	buf := new(bytes.Buffer)
	err := jpeg.Encode(buf, i.img, &jpeg.Options{Quality: quality})
	return buf.Bytes(), err
}

// ToPNG 保存为PNG格式
func (i *imgOptimizer) ToPNG() ([]byte, error) {
	buf := new(bytes.Buffer)
	err := png.Encode(buf, i.img)
	return buf.Bytes(), err
}

// ToWebp 保存为 webp 格式 (quality: 0-100)
func (i *imgOptimizer) ToWebp(quality int) ([]byte, error) {
	buf := new(bytes.Buffer)
	err := webp.Encode(buf, i.img, &webp.Options{Lossless: false, Quality: float32(quality)})
	return buf.Bytes(), err
}

// ToAvif 保存为 avif 格式 (quality: 0-100)
// func (i *imgOptimizer) ToAvif(quality int) ([]byte, error) {
// 	buf := new(bytes.Buffer)
// 	err := avif.Encode(buf, i.img, &avif.Options{
// 		Speed: avif.DefaultOptions.Speed,
// 		// Quality 0-63
// 		Quality: int((100 - quality) / 100 * avif.MaxQuality),
// 	})
// 	return buf.Bytes(), err
// }

// MarkImgWater 标记图片水印
// water 是水印图片
// transparency 是透明度，0为完全透明，255为完全不透明
func (i *imgOptimizer) MarkImgWater(water io.ReadSeeker, transparency uint8) *imgOptimizer {
	waterImg, err := imaging.Decode(water, imaging.AutoOrientation(true))
	if err != nil {
		return i
	}

	imgBounds := i.img.Bounds()

	waterBg := image.NewNRGBA(image.Rect(0, 0, imgBounds.Dx()*4, imgBounds.Dy()*4))

	newImg := image.NewNRGBA(imgBounds)                          // 按原图生成新图
	draw.Draw(newImg, imgBounds, i.img, image.Point{}, draw.Src) // 写入原图

	x, y := 0, 0
	offsetX, offsetY := 2, 25
	maxX, maxY := waterBg.Bounds().Max.X*4, waterBg.Bounds().Max.X*4
	for y <= maxY {
		for x <= maxX {
			offset := image.Pt(x, y)
			draw.Draw(waterBg, imgBounds.Bounds().Add(offset), waterImg, image.Point{}, draw.Over)
			x += waterImg.Bounds().Dx()
			x += offsetX
		}
		y += waterImg.Bounds().Dy()
		y += offsetY
		x = 0
	}

	waterBg2 := image.Image(waterBg)
	waterBg2 = transform.Rotate(waterBg2, -45.0, nil) // 倾斜
	draw.DrawMask(
		newImg,
		waterBg2.Bounds().Add(image.Pt(-waterBg2.Bounds().Dx()/2, 0)),
		waterBg2,
		image.Point{},
		image.NewUniform(color.Alpha{A: transparency}), // 255为不透明，0为完全透明
		image.Point{X: -100, Y: -100},
		draw.Over,
	)

	i.img = newImg
	return nil
}
